using GroupSix.Application.Dtos;
using GroupSix.Application.Configuration;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace GroupSix.Application.Services;

public class FileService
{
    private readonly string _uploadPath;
    private readonly ILogger<FileService> _logger;
    private readonly FileUploadOptions _options;

    public FileService(ILogger<FileService> logger, IOptions<FileUploadOptions> options)
    {
        _logger = logger;
        _options = options.Value;
        _uploadPath = _options.Path;
        
        // 确保上传目录存在
        if (!Directory.Exists(_uploadPath))
        {
            Directory.CreateDirectory(_uploadPath);
        }
    }

    public async Task<FileUploadResponseDto> UploadFileAsync(IFormFile file, FileUploadRequestDto request)
    {
        try
        {
            // 1. 验证文件
            var validationResult = ValidateFile(file);
            if (!validationResult.IsValid)
            {
                throw new InvalidOperationException(validationResult.ErrorMessage);
            }

            // 2. 生成文件信息
            var fileId = Guid.NewGuid();
            var fileExtension = Path.GetExtension(file.FileName);
            var fileName = $"{fileId}{fileExtension}";
            var relativePath = Path.Combine(request.BusinessModule, fileName);
            var fullPath = Path.Combine(_uploadPath, relativePath);

            // 3. 确保目录存在
            var directory = Path.GetDirectoryName(fullPath);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory!);
            }

            // 4. 保存文件
            using (var stream = new FileStream(fullPath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }

            // 5. 计算文件哈希
            string fileHash = string.Empty;
            if (_options.EnableHashValidation)
            {
                fileHash = CalculateFileHash(fullPath);
            }

            // 6. 返回文件信息
            var result = new FileUploadResponseDto
            {
                FileId = fileId,
                FileName = file.FileName,
                FileUrl = $"/uploads/{relativePath.Replace('\\', '/')}",
                FileType = request.FileType,
                BusinessModule = request.BusinessModule,
                BusinessId = request.BusinessId,
                Description = request.Description,
                FileSize = file.Length,
                FileHash = fileHash,
                UploadedAt = DateTime.UtcNow
            };

            _logger.LogInformation("文件上传成功: {FileName}, 大小: {FileSize}, 路径: {FilePath}", 
                file.FileName, file.Length, fullPath);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "文件上传失败: {FileName}", file.FileName);
            throw;
        }
    }

    private (bool IsValid, string ErrorMessage) ValidateFile(IFormFile file)
    {
        // 检查文件是否为空
        if (file == null || file.Length == 0)
        {
            return (false, "文件不能为空");
        }

        // 检查文件大小
        if (_options.EnableSizeValidation && file.Length > _options.MaxFileSize)
        {
            return (false, $"文件大小不能超过 {_options.MaxFileSize / 1024 / 1024}MB");
        }

        // 检查文件扩展名
        if (_options.EnableTypeValidation)
        {
            var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
            if (!_options.AllowedExtensions.Contains(extension))
            {
                return (false, $"不支持的文件类型: {extension}");
            }
        }

        // 检查文件内容类型
        if (string.IsNullOrEmpty(file.ContentType))
        {
            return (false, "无法识别文件类型");
        }

        return (true, string.Empty);
    }

    private string CalculateFileHash(string filePath)
    {
        using var sha256 = SHA256.Create();
        using var stream = File.OpenRead(filePath);
        var hash = sha256.ComputeHash(stream);
        return Convert.ToBase64String(hash);
    }

    public FileInfoDto GetFileInfo(Guid fileId)
    {
        try
        {
            // 这里应该从数据库查询文件信息
            // 暂时返回模拟数据
            return new FileInfoDto
            {
                FileId = fileId,
                FileName = "示例文件.txt",
                FileType = "text/plain",
                FileSize = 1024,
                Url = $"/uploads/{fileId}/示例文件.txt",
                UploadedAt = DateTime.UtcNow
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取文件信息失败: {FileId}", fileId);
            throw;
        }
    }

    public bool DeleteFile(Guid fileId)
    {
        try
        {
            // 这里应该从数据库查询文件路径，然后删除文件
            // 暂时返回成功
            _logger.LogInformation("文件删除成功: {FileId}", fileId);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "文件删除失败: {FileId}", fileId);
            throw;
        }
    }
} 